package cn.ydxiaoshuai.workrecord.truelicense.tools;

import cn.ydxiaoshuai.workrecord.truelicense.utils.CommonMethod;
import de.schlichtherle.license.*;
import de.schlichtherle.xml.GenericCertificate;
import de.schlichtherle.xml.XMLConstants;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * @author 小帅丶
 * @className XSLicenseManager
 * @Description 自定义LicenseManager 增加额外的校验信息
 * @Date 2021-08-12-14:35
 **/
@Slf4j
@Data
public class XSLicenseManager extends LicenseManager {

    private XSLicenseCreatorParam param;

    private static enum OS_NAME{
        windows,linux;
    }

    public XSLicenseManager(XSLicenseCreatorParam param) {
        this.param = param;
    }

    public XSLicenseManager(LicenseParam param) {
        super(param);
    }
    /** 重写create方法 */
    @Override
    protected synchronized byte[] create(LicenseContent content, LicenseNotary notary) throws Exception {
        initialize(content);
        this.validate(content);
        GenericCertificate certificate = notary.sign(content);
        return getPrivacyGuard().cert2key(certificate);
    }

    /** 重写install方法 */
    @Override
    protected synchronized LicenseContent install(byte[] key, LicenseNotary notary) throws Exception {
        return super.install(key, notary);
    }

    /** 重写verify方法  校验IP、Mac地址等等 */
    @Override
    protected synchronized LicenseContent verify(LicenseNotary notary) throws Exception {
        byte[] licenseKey = getLicenseKey();
        if(null == licenseKey){
            throw new NoLicenseInstalledException(getLicenseParam().getSubject());
        }
        GenericCertificate certificate = getPrivacyGuard().key2cert(licenseKey);
        notary.verify(certificate);
        LicenseContent content = (LicenseContent) this.load(certificate.getEncoded());
        this.validate(content);
        setCertificate(certificate);
        return content;
    }

    /**
     * 校验生成证书的参数信息
     */
    protected synchronized void validateCreate(LicenseContent content) throws LicenseContentException{
        LicenseParam licenseParam = getLicenseParam();
        Date now = new Date();
        Date notBefore = content.getNotBefore();
        Date notAfter = content.getNotAfter();

        if(null!=notAfter && now.after(notAfter)){
            throw  new LicenseContentException("Sorry,Certificate expiration time cannot be earlier than the current time");
        }

        if (null != notBefore && null != notAfter && notAfter.before(notBefore)) {
            throw new LicenseContentException("Sorry,Certificate effective time cannot be later than the certificate expiration time");
        }
        String consumerType = content.getConsumerType();

        if(null==consumerType){
            throw new LicenseContentException("Sorry,User type cannot be empty");
        }
    }

    /**
     * 重写validate方法，增加自定义校验信息
     */
    @Override
    protected synchronized void validate(LicenseContent content) throws LicenseContentException {
       //调用父类的validate方法
        super.validate(content);
    }

    /**
     * 重写validate方法，增加自定义校验信息
     */
    protected synchronized void validate(LicenseContent content,boolean checkIP,boolean checkMac,boolean checkCPU) throws LicenseContentException {
        //调用父类的validate方法
        super.validate(content);
        //校验自定义License参数，去校验自定义的license信息
        XSLicenseExtra extra = (XSLicenseExtra) content.getExtra();
        //做自定义的校验-获取服务器信息
        XSLicenseExtra serverInfos = getServerInfos();
        if(null!=extra && null!= serverInfos){
            //校验Mac地址
            if(checkMac){
                if(!CommonMethod.checkIpAddress(extra.getIpAddress(),serverInfos.getIpAddress())){
                    throw new LicenseContentException("当前服务器的Mac地址没在授权范围内");
                }
            }
            //校验IP地址
            if(checkIP){
                if(!CommonMethod.checkIpAddress(extra.getMacAddress(),serverInfos.getMacAddress())){
                    throw new LicenseContentException("当前服务器的IP没在授权范围内");
                }
            }
            //校验CPU序列号
            if(checkCPU){
                if(!CommonMethod.checkSerial(extra.getCpuSerial(),serverInfos.getCpuSerial())){
                    throw new LicenseContentException("当前服务器的IP没在授权范围内");
                }
            }
        } else {
            throw new LicenseContentException("不能获取服务器硬件信息");
        }

    }

    /**
     * 获取当前服务器需要额外校验的License参数
     */
    private XSLicenseExtra getServerInfos(){
        AbstractServerInfos abstractServerInfos = null;
       //获取操作系统类型
       String osName = System.getProperty("os.name");
       if(osName.startsWith(OS_NAME.windows.toString())){
           abstractServerInfos = new WindowsServerInfos();
       }else if(osName.startsWith(OS_NAME.linux.toString())){
           abstractServerInfos = new LinuxServerInfos();
       }else{
           abstractServerInfos = new LinuxServerInfos();
       }
       return abstractServerInfos.getServerInfos();
    }

    /**
     * 重写XMLDecoder解析XML
     */
    private Object load(String encoded){
        BufferedInputStream inputStream = null;
        XMLDecoder decoder = null;
        try {
            inputStream = new BufferedInputStream(new ByteArrayInputStream(encoded.getBytes(XMLConstants.XML_CHARSET)));
            decoder = new XMLDecoder(new BufferedInputStream(inputStream,XMLConstants.DEFAULT_BUFSIZE),null,null);
            return decoder.readObject();
        }catch (UnsupportedEncodingException e){
            log.error("XMLDecoder 编码错误", e);
            e.printStackTrace();
        }finally {
            try {
                if(decoder!=null){
                    decoder.close();
                }
                if(inputStream!=null){
                    inputStream.close();
                }
            }catch (Exception e){
                log.error("XMLDecoder解析XML失败", e);
            }
        }
        return null;
    }









































}
